home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / src / compiler / Units.sml < prev   
Encoding:
Text File  |  1997-08-18  |  13.3 KB  |  506 lines  |  [TEXT/R*ch]

  1.  
  2. open Misc BasicIO Nonstdio Fnlib Config Mixture Const Globals Location;
  3.  
  4. (* Compiled signatures *)
  5.  
  6. type CSig =
  7. {
  8.   uName:       string,
  9.   uConBasis:   (string, ConStatus) Hasht.t,
  10.   uVarEnv:     (string, TypeScheme) Hasht.t,
  11.   uTyEnv:      (string, TyName) Hasht.t,
  12.   uDatatypes:  (int, ConEnv) Hasht.t,
  13.   uStamp:      SigStamp option ref,
  14.                     (* present, if this signature comes from a .ui file *)
  15.   uMentions:   (string, SigStamp) Hasht.t
  16. };
  17.  
  18. fun conBasisOfSig   (cu : CSig) = #uConBasis cu
  19. and varEnvOfSig     (cu : CSig) = #uVarEnv cu
  20. and tyEnvOfSig      (cu : CSig) = #uTyEnv cu
  21. ;
  22.  
  23. (* The table of unit signatures already loaded in memory *)
  24.  
  25. type SigTable = (string, CSig) Hasht.t;
  26.  
  27. fun mkSigTable() = (Hasht.new 37 : SigTable);
  28. val dummySigTable = (Hasht.new 0 : SigTable);
  29.  
  30. val pervSigTable = (Hasht.new 7 : SigTable);
  31.  
  32. val currentSigTable = ref dummySigTable;
  33.  
  34. fun newSig nm : CSig =
  35. {
  36.   uName = nm,
  37.   uConBasis   = Hasht.new 13,
  38.   uVarEnv     = Hasht.new 17,
  39.   uTyEnv      = Hasht.new 7,
  40.   uDatatypes  = Hasht.new 7,
  41.   uMentions   = Hasht.new 13,
  42.   uStamp      = ref NONE
  43. };
  44.  
  45. (* Current signature *)
  46.  
  47. val dummySig = newSig "";
  48.  
  49. val currentSig = ref dummySig;
  50.  
  51. val dummyInfixBasis = (Hasht.new 0 : (string, InfixStatus) Hasht.t);
  52.  
  53. val currentInfixBasis = ref dummyInfixBasis;
  54.  
  55. val currentTypeStamp = ref 0;
  56. val currentExcStamp = ref 0;
  57. val currentValStamp = ref 0;
  58. val currentDatatypeStamp = ref 0;
  59.  
  60. val dummyRenEnv = (Hasht.new 0 : (string, int) Hasht.t);
  61.  
  62. val currentRenEnv = ref dummyRenEnv;
  63. val hasSpecifiedSignature = ref false;
  64.  
  65. (* To load a signature from a file *)
  66.  
  67. fun readSig name =
  68.   let val filename = find_in_path (name ^ ".ui")
  69.       val is = open_in_bin filename
  70.   in
  71.     let
  72.       val sigStamp = input(is, 22)
  73.       val () = if size sigStamp < 22 then raise Fail "sigStamp" else ()
  74.       val cu = (input_value is : CSig)
  75.       val {uStamp, uName, ...} = cu
  76.     in
  77.       close_in is;
  78.       uStamp := SOME sigStamp;
  79.       if name <> uName then (
  80.         msgIBlock 0;
  81.         errPrompt "File "; msgString filename;
  82.         msgString " contains the signature of unit ";
  83.         msgString uName; msgEOL();
  84.         errPrompt "instead of the signature of unit ";
  85.         msgString name; msgEOL();
  86.         msgEBlock();
  87.         raise Toplevel)
  88.       else ();
  89.       cu
  90.     end
  91.     handle Fail _ =>
  92.       (close_in is;
  93.        msgIBlock 0;
  94.        errPrompt "Corrupted compiled signature file: ";
  95.        msgString filename; msgEOL();
  96.        msgEBlock();
  97.        raise Toplevel)
  98.   end;
  99.  
  100. (* To find a pervasive signature by its name *)
  101.  
  102. fun findPervSig uname =
  103.   Hasht.find pervSigTable uname
  104.   handle Subscript =>
  105.     fatalError "findPervSig"
  106. ;
  107.  
  108. (* To find a signature by its name *)
  109.  
  110. fun findSig loc uname =
  111.   Hasht.find pervSigTable uname
  112.   handle Subscript =>
  113.     (Hasht.find (!currentSigTable) uname
  114.      handle Subscript =>
  115.        (if #uName(!currentSig) = "Top" then
  116.           (ignore(Hasht.find (!watchDog) uname)
  117.            handle Subscript =>
  118.              errorMsg loc ("Cannot access unit " ^ uname ^
  119.                            " before it has been loaded."))
  120.         else ();
  121.         let val cu =
  122.           readSig uname
  123.             handle Fail msg => errorMsg loc msg
  124.         in
  125.           Hasht.insert (!currentSigTable) uname cu; cu
  126.         end))
  127. ;
  128.  
  129. (* --- The current state of the compiler --- *)
  130.  
  131. val pervasiveInfixTable =
  132.   (Hasht.new 7 : (string, InfixStatus) Hasht.t);
  133.  
  134. val pervasiveInfixBasis = mk1TopEnv pervasiveInfixTable;
  135. val pervasiveConBasis   = ref (NILenv : (string, ConStatus) Env);
  136. val pervasiveStaticVE   = ref (NILenv : (string, TypeScheme) Env);
  137. val pervasiveStaticTE   = ref (NILenv : (string, TyName) Env);
  138.  
  139. fun initPervasiveEnvironments() =
  140. (
  141.   pervasiveConBasis   := NILenv;
  142.   pervasiveStaticVE   := NILenv;
  143.   pervasiveStaticTE   := NILenv;
  144.   List.app
  145.     (fn uname =>
  146.        let val cu = findPervSig uname in
  147.          pervasiveConBasis :=
  148.              bindTopInEnv (!pervasiveConBasis) (#uConBasis cu);
  149.          pervasiveStaticVE :=
  150.              bindTopInEnv (!pervasiveStaticVE) (#uVarEnv cu);
  151.          pervasiveStaticTE :=
  152.              bindTopInEnv (!pervasiveStaticTE) (#uTyEnv cu)
  153.        end)
  154.     pervasiveOpenedUnits
  155. );
  156.  
  157. (* Find and mention a signature *)
  158.  
  159. fun findAndMentionSig loc uname =
  160.   let val cu = findSig loc uname in
  161.     (case !(#uStamp cu) of
  162.          NONE => ()
  163.        | SOME stamp =>
  164.            let val mentions = #uMentions (!currentSig) in
  165.              ignore(Hasht.find mentions uname)
  166.              handle Subscript => Hasht.insert mentions uname stamp
  167.            end);
  168.     cu
  169.   end;
  170.  
  171. val initialConBasis   = ref (NILenv : (string, ConStatus) Env);
  172. val initialStaticVE   = ref (NILenv : (string, TypeScheme) Env);
  173. val initialStaticTE   = ref (NILenv : (string, TyName) Env);
  174.  
  175. fun initInitialEnvironments() =
  176. (
  177.   initialConBasis   := !pervasiveConBasis;
  178.   initialStaticVE   := !pervasiveStaticVE;
  179.   initialStaticTE   := !pervasiveStaticTE;
  180.   List.app
  181.     (fn uname =>
  182.        let val cu = findAndMentionSig nilLocation uname in
  183.          initialConBasis := bindTopInEnv (!initialConBasis) (#uConBasis cu);
  184.          initialStaticVE := bindTopInEnv (!initialStaticVE) (#uVarEnv cu);
  185.          initialStaticTE := bindTopInEnv (!initialStaticTE) (#uTyEnv cu)
  186.        end)
  187.     (!preopenedPreloadedUnits)
  188. );
  189.  
  190. (* To put aside the current toplevel unit while compiling another unit. *)
  191.  
  192. fun protectCurrentUnit fct =
  193.   let
  194.     val saved_currentSigTable = !currentSigTable
  195.     val saved_currentSig = !currentSig
  196.     val saved_currentInfixBasis = !currentInfixBasis
  197.     val saved_currentTypeStamp = !currentTypeStamp
  198.     val saved_currentExcStamp = !currentExcStamp
  199.     val saved_currentValStamp = !currentValStamp
  200.     val saved_currentDatatypeStamp = !currentDatatypeStamp
  201.     val saved_currentRenEnv = !currentRenEnv
  202.     val saved_initialConBasis = !initialConBasis
  203.     val saved_initialStaticVE = !initialStaticVE
  204.     val saved_initialStaticTE = !initialStaticTE
  205.   in
  206.     (
  207.     fct();
  208.     currentSigTable := saved_currentSigTable;
  209.     currentSig := saved_currentSig;
  210.     currentInfixBasis := saved_currentInfixBasis;
  211.     currentTypeStamp := saved_currentTypeStamp;
  212.     currentExcStamp := saved_currentExcStamp;
  213.     currentValStamp := saved_currentValStamp;
  214.     currentDatatypeStamp := saved_currentDatatypeStamp;
  215.     currentRenEnv := saved_currentRenEnv;
  216.     initialConBasis := saved_initialConBasis;
  217.     initialStaticVE := saved_initialStaticVE;
  218.     initialStaticTE := saved_initialStaticTE
  219.     )
  220.     handle x =>
  221.       (
  222.       currentSigTable := saved_currentSigTable;
  223.       currentSig := saved_currentSig;
  224.       currentInfixBasis := saved_currentInfixBasis;
  225.       currentTypeStamp := saved_currentTypeStamp;
  226.       currentExcStamp := saved_currentExcStamp;
  227.       currentValStamp := saved_currentValStamp;
  228.       currentDatatypeStamp := saved_currentDatatypeStamp;
  229.       currentRenEnv := saved_currentRenEnv;
  230.       initialConBasis := saved_initialConBasis;
  231.       initialStaticVE := saved_initialStaticVE;
  232.       initialStaticTE := saved_initialStaticTE;
  233.       raise x
  234.       )
  235.   end;
  236.  
  237. fun currentUnitName() =
  238.   #uName(!currentSig)
  239. ;
  240.  
  241. fun mkGlobalName id =
  242.   { qual = #uName(!currentSig), id = id }
  243. ;
  244.  
  245. fun mkGlobalInfo id info =
  246.   { qualid = mkGlobalName id, info = info }
  247. ;
  248.  
  249. fun mkUniqueGlobalName (id, stamp) =
  250.   ({ qual = #uName(!currentSig), id = id }, stamp)
  251. ;
  252.  
  253. fun newTypeStamp() =
  254. (
  255.   incr currentTypeStamp;
  256.   !currentTypeStamp
  257. );
  258.  
  259. fun newExcStamp() =
  260. (
  261.   incr currentExcStamp;
  262.   !currentExcStamp
  263. );
  264.  
  265. fun newValStamp() =
  266. (
  267.   incr currentValStamp;
  268.   !currentValStamp
  269. );
  270.  
  271. fun newDatatypeStamp() =
  272. (
  273.   incr currentDatatypeStamp;
  274.   !currentDatatypeStamp
  275. );
  276.  
  277. (* Additions to the unit being compiled *)
  278.  
  279. fun add_global_info sel_fct id info =
  280.   let val tbl = sel_fct (!currentSig) in
  281.     Hasht.insert tbl id info
  282.   end
  283. ;
  284.  
  285. fun add_InfixBasis id info =
  286.   Hasht.insert (!currentInfixBasis) id info
  287. ;
  288.  
  289. val add_ConBasis = add_global_info conBasisOfSig
  290. and add_VarEnv   = add_global_info varEnvOfSig
  291. and add_TyEnv    = add_global_info tyEnvOfSig
  292. ;
  293.  
  294. (* Additions to the unit being compiled *)
  295. (* without redefining names that are already bound! *)
  296.  
  297. fun extend_ConBasis id info =
  298.   let val tbl = conBasisOfSig (!currentSig) in
  299.     (ignore (Hasht.find tbl id);
  300.      msgIBlock 0;
  301.      errPrompt "Value identifier ";
  302.      msgString id; msgString " cannot be redefined in a signature.";
  303.      msgEOL();
  304.      msgEBlock();
  305.      raise Toplevel)
  306.     handle Subscript =>
  307.       Hasht.insert tbl id info
  308.   end;
  309.  
  310. fun extend_TyEnv id info =
  311.   let val tbl = tyEnvOfSig (!currentSig) in
  312.     (ignore (Hasht.find tbl id);
  313.      msgIBlock 0;
  314.      errPrompt "Type constructor ";
  315.      msgString id; msgString " cannot be redefined in a signature.";
  316.      msgEOL();
  317.      msgEBlock();
  318.      raise Toplevel)
  319.     handle Subscript =>
  320.       Hasht.insert tbl id info
  321.   end;
  322.  
  323. (* Find the information for a reference to a qualified identifier. *)
  324.  
  325. fun findInfo sel_fct env loc q =
  326.   let val {qual, id} = q in
  327.     if qual = "" then
  328.       lookupEnv env id
  329.     else if qual = #uName(!currentSig) then
  330.       (msgIBlock 0;
  331.        errLocation loc;
  332.        errPrompt "Qualifier cannot refer to the current unit: ";
  333.        printQualId q; msgEOL();
  334.        msgEBlock();
  335.        raise Toplevel)
  336.     else
  337.       Hasht.find (sel_fct (findAndMentionSig loc qual)) id
  338.   end;
  339.  
  340. (* Find constructors for a datatype. *)
  341.  
  342. fun findConstructors (sign : CSig) stamp =
  343.   Hasht.find (#uDatatypes sign) stamp
  344.   handle Subscript => fatalError "findConstructors"
  345. ;
  346.  
  347. fun setConstructors (sign : CSig) stamp CE =
  348.   Hasht.insert (#uDatatypes sign) stamp CE
  349. ;
  350.  
  351. fun registerConstructors CE =
  352.   let val stamp = newDatatypeStamp() in
  353.     setConstructors (!currentSig) stamp CE;
  354.     stamp
  355.   end;
  356.  
  357. (* We have to compare the whole qualids, because in exported *)
  358. (* TyNames all stamps are reset to 0. Therefore, different   *)
  359. (* exported TyNames may have equal stamps. *)
  360.  
  361. fun isEqTN (tn1 : TyName) (tn2 : TyName) =
  362.   #qualid tn1 = #qualid tn2 andalso
  363.   #tnStamp (!(#info tn1)) = #tnStamp (!(#info tn2))
  364. ;
  365.  
  366. fun updateCurrentInfixBasis iBas =
  367.   traverseEnv add_InfixBasis (revEnv iBas)
  368. ;
  369.  
  370. fun updateCurrentConBasis cBas =
  371.   traverseEnv add_ConBasis (revEnv cBas)
  372. ;
  373.  
  374. fun extendCurrentConBasis cBas =
  375.   traverseEnv extend_ConBasis (revEnv cBas)
  376. ;
  377.  
  378. fun updateCurrentStaticVE VE =
  379.   traverseEnv add_VarEnv (revEnv VE)
  380. ;
  381.  
  382. fun updateCurrentStaticTE TE =
  383.   traverseEnv add_TyEnv (revEnv TE)
  384. ;
  385.  
  386. fun extendCurrentStaticTE TE =
  387.   traverseEnv extend_TyEnv (revEnv TE)
  388. ;
  389.  
  390. fun mkGlobalInfixBasis() =
  391.   bindTopInEnv pervasiveInfixBasis (!currentInfixBasis)
  392. ;
  393.  
  394. fun mkGlobalConBasis() =
  395.   bindTopInEnv (!initialConBasis) (#uConBasis (!currentSig))
  396. ;
  397.  
  398. fun mkGlobalVE() =
  399.   bindTopInEnv (!initialStaticVE) (#uVarEnv (!currentSig))
  400. ;
  401.  
  402. fun mkGlobalTE() =
  403.   bindTopInEnv (!initialStaticTE) (#uTyEnv (!currentSig))
  404. ;
  405.  
  406. fun execToplevelOpen loc uname =
  407.   let val cu = findAndMentionSig loc uname in
  408.     updateCurrentConBasis (mk1TopEnv (#uConBasis cu));
  409.     updateCurrentStaticVE (mk1TopEnv (#uVarEnv cu));
  410.     updateCurrentStaticTE (mk1TopEnv (#uTyEnv cu))
  411.   end;
  412.  
  413. fun printHiddenId id =
  414.   (msgString "?{"; msgString id; msgString "}")
  415. ;
  416.  
  417. fun printVQ q =
  418.   let val {qual, id} = q
  419.       fun printHidden() =
  420.             if qual <> #uName(!currentSig) then
  421.               (msgString qual; msgString ".";
  422.                msgString id)
  423.             else
  424.               printHiddenId id
  425.   in
  426.     (if #qual(#qualid (lookupEnv (mkGlobalConBasis()) id)) = qual then
  427.         msgString id
  428.       else
  429.         printHidden())
  430.     handle Subscript =>
  431.       printHidden()
  432.   end;
  433.  
  434. fun printTQ tn =
  435.   let val {qualid, info} = tn
  436.       val {qual, id} = qualid
  437.       fun printHidden() =
  438.             if qual <> #uName(!currentSig) then
  439.               (msgString qual; msgString ".";
  440.                if #tnStamp(!info) <> 0 then
  441.                  printHiddenId id
  442.                else
  443.                  msgString id)
  444.             else
  445.               printHiddenId id
  446.   in
  447.     let val tn0 = lookupEnv (mkGlobalTE()) id in
  448.       if isEqTN tn tn0 then msgString id else printHidden()
  449.     end
  450.     handle Subscript =>
  451.       printHidden()
  452.   end;
  453.  
  454. fun mkInfixBasis() = (Hasht.new 13 : (string, InfixStatus) Hasht.t);
  455. fun mkRenEnv() = (Hasht.new 113 : (string, int) Hasht.t);
  456.  
  457. fun startCompilingUnit name =
  458. (
  459.   currentSigTable := mkSigTable();
  460.   currentSig := newSig name;
  461.   currentInfixBasis := mkInfixBasis();
  462.   currentTypeStamp := 0;
  463.   currentExcStamp := 0;
  464.   currentValStamp := 0;
  465.   currentDatatypeStamp := 0;
  466.   currentRenEnv := mkRenEnv()
  467. );
  468.  
  469. fun rectifyConBasis cBas =
  470.   let
  471.     val excRen = ref( [] : (QualifiedIdent * (QualifiedIdent * int)) list )
  472.   in
  473.     Hasht.apply (fn id => fn (status : ConStatus) =>
  474.         case #info status of
  475.             EXNname ei =>
  476.               (case #exconTag(!ei) of
  477.                    NONE => fatalError "rectifyConBasis"
  478.                  | SOME (name, stamp) =>
  479.                      if #qual(#qualid status) = #uName(!currentSig) then
  480.                        excRen := (#qualid status, (name, stamp)) :: !excRen
  481.                      else ())
  482.           | _ => ())
  483.       cBas;
  484.     (!excRen)
  485.   end;
  486.  
  487. fun rectifyCurrentTyEnv() =
  488.   let val tyEnv = #uTyEnv (!currentSig) in
  489.     Hasht.apply (fn _ => fn tn =>
  490.         let val {info, ...} = tn in
  491.           if #tnStamp(!info) <> 0 then (setTnStamp info 0) else ()
  492.         end)
  493.       tyEnv
  494.   end;
  495.  
  496. fun rectifySignature() =
  497.   let val () = rectifyCurrentTyEnv()
  498.       val excRenList = rectifyConBasis (#uConBasis(!currentSig))
  499.       val valRenList =
  500.         foldEnv (fn id => fn stamp => fn acc => (id,stamp)::acc)
  501.                 [] (mk1TopEnv (!currentRenEnv))
  502.   in
  503.     currentRenEnv := dummyRenEnv;
  504.     (excRenList, valRenList)
  505.   end;
  506.